<?php

namespace ImiApp\ApiServer\Common\Store;

use Imi\Config;
use Imi\Log\Log;
use Imi\RequestContext;
use Imi\Server\Http\Message\Proxy\RequestProxy;
use Imi\Util\ClassObject;
use Imi\Util\Http\Consts\ResponseHeader;
use Imi\Util\Http\Consts\MediaType;
use Exception;
use ImiApp\ApiServer\Common\Auth\AuthManager;
use Imi\Aop\AroundJoinPoint;
use Imi\Bean\Annotation\Inherit;


use Imi\Aop\Annotation\Aspect;
use Imi\Aop\Annotation\PointCut;
use Imi\Aop\PointCutType;




class StoreAop
{
    protected ?string $name;
    protected $nologin;



    public function __construct(?string $name, $nologin)//, $nocheck
    {
        var_dump('Store aop name',$name);
        $this->name = $name;
        $this->nologin = $nologin;
        // $this->nocheck = $nocheck;
        $this->config = Config::get('@app.beans.AuthConfig');
    }





   /**
     * Auth注解切入
     * @param AroundJoinPoint $joinPoint
     * @return mixed
     */
    public function parseAuth(AroundJoinPoint $joinPoint)
    {
        var_dump('StoreAop parseAuth');
        if (!($this->config['status'] ?? false)) {
            Log::info("Auth is closed");
            return false;
        }
        if (!isset($this->config[$this->name]) && !isset($this->config['default'])) {
            Log::error("AuthConfig is not defined");
            return false;
        }
        $name = isset($this->config[$this->name]) ? $this->name : 'default';
        $config = $this->config[$name];
        $response = RequestContext::get('response');
        $request = new RequestProxy;
        $authManager = new AuthManager($name);
        if (!$authManager->isLogin()) {
            return $this->response($config['error']);
        }
        var_dump('Store aop login id',$authManager->user()->id);
        try {
            $routeItem = RequestContext::get('routeResult')->routeItem->callable;
            $class = trim($routeItem->getBeanName(), '/');
            $method = $routeItem->getMethodName();
        } catch (Exception $e) {
            Log::error('Get routeItem error.');
            return $this->response($config['error']);
        }
        if ($this->nocheck !== '*' && !in_array($joinPoint->getMethod(), (array)$this->nocheck) && ($config['check'] ?? false)) {
            if (!$authManager->check($class . '::' . $method)) {
                return $this->response($config['error']);
            }
        }
        $args = ClassObject::convertArgsToKV($class, $method, $joinPoint->getArgs());
        $args['user'] = $authManager->user();
        // log
        if ($config['model']['operate_log'] ?? false) {
            $model = $config['model']['operate_log'];
            if (method_exists($model, 'write')) {
                $model::write([
                    'user_id' => $args['user']->id,
                    'route' => RequestContext::get('routeResult')->routeItem->annotation->url ?? '',
                    'controller' => $class . '::' . $method,
                    'ip' => ip(),
                    'user_agent' => $request->getHeaderLine('User-Agent'),
                    'content' => json_encode(array_merge((array)$request->request(), (array)$request->getParsedBody()), 256 | 64),
                ]);
            }
        }
        // log
        $args = array_values($args);
        $joinPoint->setArgs($args);
        return $joinPoint->proceed($args);
    }

    /**
     * 拦截响应
     * @param string $msg
     * @param int $code
     * @return mixed
     */
    private function response(string $msg ="错误",int $code = -1)
    {
        $response = RequestContext::get('response');
        $response->setHeader(ResponseHeader::CONTENT_TYPE, MediaType::APPLICATION_JSON_UTF8)
            ->setHeader('Access-Control-Allow-Origin', "*")
            ->setStatus(200)
            ->getBody()->write(json_encode([
                'code' => $code,
                'message' => '没有店铺角色',
            ], 256 | 64));
        return $response;
    }
}